<?php
/**
 * Allows developers to log and time parts of their code
 */
class Logger {
	const INFO = 1;
	const WARNING = 2;
	const ERROR = 3;

	/**
	 * Holds when the init() method was called
	 *
	 * @var float $startTime
	 */
	private static $startTime;

	/**
	 * Keeps track of logs / calls to log()
	 *
	 * @var array $logs
	 */
	private static $logs;

	/**
	 * Initilizes the logger
	 */
	public static function init ($initialLog = 'Logger initialized.') {
		self::$startTime = microtime(true);
		self::log($initialLog, __METHOD__);
	}

	/**
	 * Adds a new $log from $origin (preferably __METHOD__, __FUNCTION__ or __FILE__)
	 *
	 * @param string $log
	 * @param string $origin
	 */
	public static function log ($log, $origin, $type = self::INFO) {
		if (DEBUG) {
			self::$logs[] = array(
				'log'			=> $log, 
				'start_time'	=> microtime(true), 
				'origin'		=> $origin, 
				'mem_usage'		=> memory_get_usage(), 
				'type'			=> $type
			);
		}
	}

	/**
	 * Returns the time between init and now, 
	 * or false if self::$startTime is unset
	 */
	public static function getRunTime () {
		if (self::$startTime === null) {
			return false;
		}

		return microtime(true) - self::$startTime;
	}

	/**
	 * Returns all the logs with some extra info as an array
	 */
	public static function getLogs () {
		$logs = self::$logs;
		$prevK = false;

		foreach ($logs as $k => $log) {
			# Calculate the difference in time between this log and the previous one
			$logs[$k]['diff'] = ($prevK ? $log['start_time'] - $logs[$prevK]['start_time'] : $log['start_time'] - self::$startTime);

			# Calculate total time so far since init()-call
			$logs[$k]['total'] = $log['start_time'] - self::$startTime;

			$prevK = $k;
		}

		return $logs;
	}

	/**
	 * Returns all the logs with some extra info as an HTML table
	 */
	public static function getLogsAsHTML () {
		$logs = self::getLogs();
		$html = '<table><thead><tr><th>Log</th><th>Diff</th><th>Total</th><th>Memory</th></tr></thead><tbody>';

		foreach ($logs as $log) {
			$html .= '<tr><td>'
						. ($log['type'] == self::WARNING ? '<strong>Warning:</strong> ' : '') 
						. ($log['type'] == self::ERROR ? '<strong><strong>Error:</strong></strong> ' : '') 
						. '<b>' . basename($log['origin']) . '</b>: ' 
						. $log['log'] 
						. '</td><td>' 
						. round($log['diff'] * 1000, 2) 
						. 'ms</td><td>' 
						. round($log['total'] * 1000, 1) 
						. 'ms</td><td>' 
						. round($log['mem_usage'] / 1024, 1) 
						. 'kb</td></tr>';
		}

		$html .= '</tbody></table>';

		return $html;
	}

	/**
	 * Returns all the logs with some extra info as javascript
	 * that, when executed, logs all the logs in the console
	 */
	public static function getLogsInConsole () {
		$logs = self::getLogs();
		$html = '<script>';

		foreach ($logs as $log) {
			$html .= 'console.log("' 
						. ($log['type'] == self::WARNING ? '[Warning] ' : '') 
						. ($log['type'] == self::ERROR ? '[Error] ' : '') 
						. basename($log['origin']) 
						. ': ' 
						. addslashes($log['log']) 
						. ', ' 
						. round($log['diff'] * 1000, 2) 
						. 'ms, ' 
						. round($log['total'] * 1000, 1) 
						. 'ms, ' 
						. round($log['mem_usage'] / 1024, 1) 
						. 'kb");';
		}

		$html .= '</script>';

		return $html;
	}
}
